﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Emu8080.Compiler;
using Emu8080.Compiler.Structures;

namespace CompilerTool
{
    class Program
    {
        const string UsageString = "Usage: CompilerTool [-o outputFile] inputFile";

        static void Main(string[] args)
        {
            string inputFile;
            string outputFile = null;

            bool error = args.Length == 0;
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == "-o")
                {
                    if (i + 1 < args.Length - 1)
                    {
                        outputFile = args[i + 1];
                    }
                    else
                        error = true;
                }
            }

            if (error)
            {
                Console.WriteLine("Error parsing command line arguments.");
                Console.WriteLine(UsageString);
            }
            else
            {
                inputFile = args[args.Length - 1];
                if (!File.Exists(inputFile))
                {
                    Console.WriteLine("Input file not found.");
                    Console.WriteLine(UsageString);
                }
                else
                {
                    var s = File.ReadAllText(inputFile);
                    var @out = Build(s);
                    if (outputFile != null)
                    {
                        File.WriteAllText(outputFile, @out, Encoding.UTF8);
                    }
                    else
                    {
                        Console.WriteLine();
                        Console.WriteLine(@out);
                    }
                }

            }


        }

        static string Build(string source)
        {
            Compiler compiler = new Compiler(source);
            compiler.OnError +=new MessageHandler(compiler_OnError);
            var program = compiler.Compile();
            
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(string.Format("Program start address: {0:X4}", program.StartAddress));
            sb.AppendLine();
            foreach (var item in program.Module.ProcessingUnits)
	        {
                if (item is IProcessingUnitFundamental)
                {
                    var f = item as IProcessingUnitFundamental;
                    var byteString = "";
                    var machCodes = f.GetMachineCodes();
                    for (int i = 0; i < machCodes.Length && i < 4; i++)
                    {
                        var bt = machCodes[i];
                        byteString += string.Format("{0:X2} ", bt);
                    }
                    string s = string.Format("{0:X4}\t{1,-12}\t{2}", f.Address, byteString, f.Meta.LineContent);
                    sb.AppendLine(s);
                }
                else
                {
                    string s = string.Format("    \t            \t{0}", item.Meta.LineContent);
                    sb.AppendLine(s);
                }
	        }
            return sb.ToString();
        }

        static void compiler_OnError(int line, int pos, string message)
        {
            Console.WriteLine("Error: {0}:{1} - {2}", line, pos, message);
        }
    }
}
